﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using InHD.model;
using InHD.dataaccess;
using InHD.commands;
using System.Collections.ObjectModel;
using System.Windows.Input;
using InHD.utilities;
using System.Windows;
using System.Data;
using System.Collections.Specialized;
using System.ComponentModel;
using InHD.Properties;

namespace InHD.viewmodels
{
    class SaleViewModel : WorkspaceViewModel
    {
        #region Private variables
        Transaction _trans;
        readonly CompanyInfo _companyInfo;
        TransactionRepository _transRepo = null;
        PackageRepository _packageRepo = null;
        TaxRepository _taxRepo = null;
        ProductRepository _proRepo = null;
        CategoryRepository _categoryRepo = null;
        RegisterPrintingRepository _regRepo = null;
        InvoiceTemplateRepository _invoiceRepo = null;
        InvoicePrinter _invoicePrinter = null;

        Customer _currentCustomer = Customer.CreateCustomer();
        CustomerRepository _cusRepo = null;

        RelayCommand _addProductCommand;
        RelayCommand _removeProductCommand;
        RelayCommand _saleCommand;

        private RelayCommand _selectCommand;
        private RelayCommand _closeProductsCommand;
        private RelayCommand _searchCommand;
        private RelayCommand _addToPackageCollectionCommand;
        private RelayCommand _changeSaleTypeCommand;
        private RelayCommand _searchCustomerCommand;
        private RelayCommand _chooseProductCommand;

        private bool _isIncludeTax;
        private bool _isWholesale;        

        private ObservableCollection<Package> _pacs=  new ObservableCollection<Package>();
        List<Product> _products;
        private Package _selectedPackage = null;
        private Tax _selectedTax = null;
        private Package _currentPackage;
        private DateTime _invoiceDate;

        private bool _isInvalidCustomerCode = false;
        
        #endregion

        #region Creation
        public SaleViewModel(CompanyInfo companyInfo)
        {
            this._companyInfo = companyInfo;
            this._transRepo = new TransactionRepository();
            this._packageRepo = new PackageRepository();
            this._taxRepo = new TaxRepository();
            this._proRepo = new ProductRepository();
            this._categoryRepo = new CategoryRepository();
            this._cusRepo = new CustomerRepository();
            this._invoiceRepo = new InvoiceTemplateRepository();
            this._regRepo = new RegisterPrintingRepository();

            this._categoryRepo.LoadAllCategories();
            this._cusRepo.LoadAllCustomers();
            this.ProductFields = Product.Fields;
            this._products = new List<Product>();
            this._taxRepo.LoadAllTaxTypes();
            Taxs = _taxRepo.GetAllTaxes();
            this._currentPackage = Package.CreatePackage();
            if (string.IsNullOrEmpty(this._invoiceRepo.LoadAllInvoiceTplByTransType(TransTypes.Sale)))
            {
                InvoiceTplCollection = this._invoiceRepo.GetInvoiceTemplate();
            }

            CustomerFields = Customer.Fields;

            this.CustomerRowIndex = -1;
            this.RowIndex = -1;
            this._invoiceDate = System.DateTime.Now;
        }
        #endregion

        #region Public fields
        public string StaffUNK;

        public string SerialNo
        {
            get { return this._currentPackage.SerialNo; }
            set { this._currentPackage.SerialNo = value; base.OnPropertyChanged("SerialNo"); }
        }

        public string Description
        {
            get { return this._currentPackage.Description; }
            set { this._currentPackage.Description = value;}
        }

        public string CategoryName
        {
            get { return this._currentPackage.CategoryName; }
            set { this._currentPackage.CategoryName = value; }
        }

        public double UnitPrice
        {
            get { return this._currentPackage.UnitPrice; }
            set
            {
                this._currentPackage.UnitPrice = value;
            }
        }

        public int Quantity
        {
            get { return this._currentPackage.Quantity; }
            set
            {
                this._currentPackage.Quantity = value;
            }
        }

        public int RowIndex { get; set; }

        private Product _currentProduct = Product.CreateProduct();
        public Product CurrentProduct
        {
            get
            {
                return _currentProduct;
            }
            set
            {
                if (!string.IsNullOrEmpty(((Product)value).Name))
                {
                    for (int i = 0; i < this.PackagesCollection.Count; i++)
                    {
                        Package p = this.PackagesCollection[i];
                        if (!string.IsNullOrEmpty(p.ProductUNK) && p.ProductUNK.Equals(((Product)value).ProductUNK))
                        {
                            int tmp2 = GetRowIndexByItem(SelectedPackage);
                            Package tmpPack = this.PackagesCollection[tmp2];
                            this.PackagesCollection.RemoveAt(tmp2);
                            this.PackagesCollection.Insert(tmp2, tmpPack); 
                                MessageBox.Show(Resources.Product_Existing, Resources.App_Title, MessageBoxButton.OK, MessageBoxImage.Information);
                            this.SelectedPackage = this.PackagesCollection[i];
                            OnPropertyChanged("SelectedPackage");
                            return;
                        }
                    }

                    string description = ((Product)value).Description;
                    string serialNo = ((Product)value).SerialNo;
                    double price = this._isWholesale ? ((Product)value).WholesalePrice : ((Product)value).RetailPrice;
                    this._currentPackage = Package.CreateBusinessPackage(serialNo, description, ((Product)value).CategoryName, price, 1, ((Product)value).Name);

                    this._currentPackage.PackageUNK = "Pac-" + Guid.NewGuid().ToString();
                    this._currentPackage.ProductUNK = ((Product)value).ProductUNK;

                    this._currentPackage.SaveRetail = ((Product)value).RetailPrice;
                    this._currentPackage.SaveWholesale = ((Product)value).WholesalePrice;
                    this._currentPackage.SaveImportPrice = ((Product)value).ImportPrice;
                    int temp = this.GetRowIndexByItem(this.SelectedPackage);
                    this.PackagesCollection[temp] = this._currentPackage;
                    this.PackagesCollection[temp].PropertyChanged += EntityViewModelPropertyChanged;
                    this.PackagesCollection[temp].Quantity = 1;
                    OnPropertyChanged("SelectedPackage");
                }
            }
        }

        public Package SelectedPackage
        {
            get
            {
                return this._selectedPackage;
            }

            set 
            {
                this._selectedPackage = value;
            }
        }

        public DateTime InvoiceDate
        {
            get
            {
                return _invoiceDate;
            }
            set
            {
                if (!_invoiceDate.Equals(value))
                {
                    _invoiceDate = value;
                    OnPropertyChanged("InvoiceDate");
                }
            }
        }

        public List<Tax> Taxs
        {
            get;
            private set;
        }

        public Tax SelectedTax
        {
            get
            {
                return this._selectedTax;
            }
            set
            {
                this._selectedTax = value;
                if (value == null)
                {
                    this.totalIncTax = this.totalExTax;
                }
                else
                {
                    this.totalIncTax = this.totalExTax * (1 + this._selectedTax.Percentage);
                }
                
                OnPropertyChanged("TotalPriceIncTax");
                OnPropertyChanged("TotalPriceTax");
            }
        }

        public bool IsIncludeTax
        {
            get { return this._isIncludeTax; }
            set
            {
                this._isIncludeTax = value;
                base.OnPropertyChanged("IsIncludeTax");
                this.SelectedTax = null;
                base.OnPropertyChanged("SelectedTax");
            }
        }

        public string TotalPriceExTax
        {
            get 
            {
                totalExTax = 0;
                foreach (Package p in this.PackagesCollection)
                {
                    totalExTax += p.PackagePrice;
                }

                OnPropertyChanged("TotalPriceIncTax");
                return Resources.Ex_Tax + this.totalExTax.ToString();
            }
        }

        public string TotalPriceTax
        {
            get 
            {
                return (this.SelectedTax == null) ? Resources.Tax_Title + " 0 %" : Resources.Tax_Title + ((long)(this.SelectedTax.Percentage * 100)).ToString() + " %";
            }
        }

        public string TotalPriceIncTax
        {
            get 
            {
                if (this.SelectedTax != null)
                {
                    this.totalIncTax = this.totalExTax * (1 + this.SelectedTax.Percentage);
                }
                else
                {
                    this.totalIncTax = this.totalExTax;
                }
                return Resources.Inc_Tax + ((long)this.totalIncTax).ToString();
            }
        }

        public bool IsWholesale
        {
            get { return this._isWholesale; }
            set
            {
                this._isWholesale = value;
                base.OnPropertyChanged("IsWholesale");
            }
        }


        public ObservableCollection<Package> PackagesCollection
        {
            get
            {
                return this._pacs;
            }
            set
            {
                if (_pacs != value)
                {
                    this._pacs = value;
                    OnPropertyChanged("PackagesCollection");
                    OnPropertyChanged("TotalPriceExTax");
                }
            }
        }

        public PaymentTypes PaymentType
        {
            get;
            set;
        }

        public List<InvoiceTemplate> InvoiceTplCollection { get; set; }

        public int InvoiceTplIndex { get; set; }

        /// <summary>
        /// Represent DataSource of listview for selecting product in search dialog
        /// </summary>
        public List<Product> Products
        {
            get { return this._products; }
            set { this._products = value; base.OnPropertyChanged("Products"); }
        }

        /// <summary>
        /// Represent ItemSource for select property selected in search dialog
        /// </summary>
        public Dictionary<string, string> ProductFields { get; set; }

        /// <summary>
        /// ItemSource for select category (in search dialog and product workspace)
        /// </summary>
        public List<Category> Categories { get { return this._categoryRepo.GetCategory(); } }

        /// <summary>
        /// Represent Property for search selected in search dialog
        /// </summary>
        public string SelectedProperty { get; set; }

        /// <summary>
        /// Represent Search Criteria typed in search dialog
        /// </summary>
        public string SearchCriteria { get; set; }

        /// <summary>
        /// Represent Category selected in search dialog
        /// </summary>
        public Category SelectedCategory
        {
            get;
            set;
        }

        public string CustomerCode
        {
            get
            { return this._currentCustomer.CustomerCode; }
            set
            {
                this._currentCustomer.CustomerCode = value;
                OnPropertyChanged("CustomerCode");
            }
        }
        public string CustomerName
        {
            get
            { return this._currentCustomer.FirstName; }
            set
            {
                this._currentCustomer.FirstName = value;
                OnPropertyChanged("CustomerName");
            }
        }

        public bool IsInvalidCustomerCode
        {
            get
            { return this._isInvalidCustomerCode; }
            set
            {
                this._isInvalidCustomerCode = value;
                OnPropertyChanged("IsInvalidCustomerCode");
            }
        }

        public bool InvoicePreview { get; set; }

        /// <summary>
        /// Returns a command that add new Product.
        /// </summary>
        public ICommand AddNewProductCommand
        {
            get
            {
                if (_addProductCommand == null)
                {
                    _addProductCommand = new RelayCommand(
                        (param) => this.AddProduct(), param => CanAddNewProduct);
                }
                return _addProductCommand;
            }
        }

        /// <summary>
        /// Returns a command that remove the product.
        /// </summary>
        public ICommand RemoveProductCommand
        {
            get
            {
                if (_removeProductCommand == null)
                {
                    _removeProductCommand = new RelayCommand(
                        (param) => this.RemoveProduct(), (param) => this.CanRemove);
                }
                return _removeProductCommand;
            }
        }

        public ICommand ChangeSaleTypeCommand
        {
            get
            {
                if (_changeSaleTypeCommand == null)
                {
                    _changeSaleTypeCommand = new RelayCommand(
                        (param) => this.ChangeSaleType());
                }
                return _changeSaleTypeCommand;
            }
        }

        public ICommand AddToPackageCollectionCommand
        {
            get
            {
                if (_addToPackageCollectionCommand == null)
                {
                    _addToPackageCollectionCommand = new RelayCommand(
                        (param) => this.AddToPackageCollection(), (param) => this.CanAddToPackageCollection);
                }
                return _addToPackageCollectionCommand;
            }
        }

        public ICommand SelectProductForPackageCommand
        {
            get
            {
                if (_chooseProductCommand == null)
                {
                    _chooseProductCommand = new RelayCommand(
                        (param) => this.ChooseProduct());
                }
                return _chooseProductCommand;
            }
        }

        /// <summary>
        /// Returns a command that commit Window
        /// </summary>
        public ICommand SaleCommand
        {
            get
            {
                if (_saleCommand == null)
                {
                    _saleCommand = new RelayCommand(
                        (param) => this.Sale(param), (param) => this.CanSale);
                }
                return _saleCommand;
            }
        }

        public ICommand SelectCommand
        {
            get
            {
                if (_selectCommand == null)
                {
                    _selectCommand = new RelayCommand(
                        (param) => this.SelectProduct(),(param)=>CanSelectProduct
                        );
                }
                return _selectCommand;
            }
        }

        public ICommand CloseProductsCommand
        {
            get
            {
                if (_closeProductsCommand == null)
                {
                    _closeProductsCommand = new RelayCommand(
                        (param) => this.CloseProducts()
                        );
                }
                return _closeProductsCommand;
            }
        }

        public ICommand SearchCommand
        {
            get
            {
                if (_searchCommand == null)
                {
                    _searchCommand = new RelayCommand(
                        (param) => this.SearchProducts()
                        );
                }
                return _searchCommand;
            }
        }

        public ICommand SearchCustomerCommand
        {
            get
            {
                if (_searchCustomerCommand == null)
                {
                    _searchCustomerCommand = new RelayCommand(
                        (param) => this.SearchCustomer()
                        );
                }
                return _searchCustomerCommand;
            }
        }
        #endregion       

        #region Private Helpers
        private void SearchCustomer()
        {
            List<Customer> tmpList = this._cusRepo.GetProductsWthSearchCriteria("CustomerCode", this.CustomerCode);
            if (tmpList != null && tmpList.Count > 0)
            {
                this._currentCustomer = tmpList[0];
                this.IsInvalidCustomerCode = false;
            }
            else
            {
                this.IsInvalidCustomerCode = true;
            }
        }

        private void Sale(object param)
        {
            if (this._currentCustomer == null || string.IsNullOrEmpty(this._currentCustomer.CustomerUNK))
            {
                MessageBox.Show("Please select Customer");
                return;
            }

            string resultPrepare = PreparePrint();
            if (!string.IsNullOrEmpty(resultPrepare))
            {
                MessageBox.Show(resultPrepare);
                return;
            }

            if (this.InvoicePreview)
            {
                this.DoPrinterPreview();
            }

            double disCount = 0;

            this._trans = Transaction.CreateTransaction(
                this.InvoiceDate,
                this.IsIncludeTax && this.SelectedTax != null ? this.SelectedTax.TaxUNK : "001",
                disCount,
                this.totalIncTax,
                InvoiceTplCollection[InvoiceTplIndex].InvoiceUNK,
                TransTypes.Sale,
                "001",//// account UNK
                this._currentCustomer.CustomerUNK,
                this.StaffUNK,
                0,
                this._currentCustomer.FirstName,
                this._currentCustomer.LastName,
                this.IsIncludeTax && this.SelectedTax != null ? this.SelectedTax.Description : string.Empty,
                this.IsIncludeTax && this.SelectedTax != null ? this.SelectedTax.Percentage : 0,
                this.PaymentType);

            string archiveFlag = string.Empty;
            if (MessageBox.Show(Resources.Ask_PayNow, Resources.App_Title, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                archiveFlag = _trans.TransactionUNK;
                if (totalIncTax < 200)
                {
                    if (MessageBox.Show(Resources.Ask_Receive_invoice, Resources.App_Title, MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                    {
                        DoPrint();
                    }
                }
                else
                {
                    DoPrint();
                }
            }

            _trans.ArchiveFlag = archiveFlag;
            string result = this._transRepo.AddTransaction(_trans, _pacs, 1);
            if (string.IsNullOrEmpty(result))
            {
                MessageBox.Show(Resources.InHD_TransactionCommited, Resources.App_Title, MessageBoxButton.OK);
            }
            else
            {
                MessageBox.Show(Resources.InHD_DB_Error, Resources.App_Title, MessageBoxButton.OK);
            }

            ResetWorkSpace();
        }

        private void DoPrinterPreview() 
        {
            _invoicePrinter.ShowPrintPreview();
        }

        private void DoPrint()
        {
            _invoicePrinter.PutSpan("spanLien", Resources.Print_Lien1);
            _invoicePrinter.Print(true);
            _invoicePrinter.PutSpan("spanLien", Resources.Print_Lien2);
            _invoicePrinter.Print(false);
        }

        private string PreparePrint()
        {
            DataRow regRow = this._regRepo.CheckRegisterExistenceByInvoiceTpl(InvoiceTplCollection[InvoiceTplIndex].InvoiceUNK);
            if (regRow == null) return "No registration is found.";
            DateTime expiredDate = Convert.ToDateTime(regRow["expiredDate"]);
            if (expiredDate < this.InvoiceDate)
            {
                return "Expired registration";
            }

            int maxNumberOfUse = Convert.ToInt16(regRow["maxUsingTimes"]);
            int remainUse = Convert.ToInt16(regRow["number"]);
            int regID = Convert.ToInt16(regRow["id"]);
            string spanKH01 = Convert.ToChar(regID / 26 + 65).ToString() + Convert.ToChar(regID % 26 + 65).ToString();

            string tableName = "tableContent";
            string[] listColumn = { "1", "2", "3", "4", "5", "6" };
            DataTable dataTable = new DataTable();
            foreach (string col in listColumn)
            {
                dataTable.Columns.Add(col);
            }

            int count = 0;
            foreach (Package pack in PackagesCollection)
            {
                count++;
                DataRow row = dataTable.NewRow();
                row[0] = count;
                row[1] = pack.ProductName;
                row[2] = "N/A";
                row[3] = pack.Quantity;
                row[4] = pack.UnitPrice;
                row[5] = pack.PackagePrice;
                dataTable.Rows.Add(row);
            }

            _invoicePrinter = new InvoicePrinter(this.InvoiceTplCollection[InvoiceTplIndex].InvoiceUNK);
            _invoicePrinter.PutDataTable(tableName, dataTable);
            _invoicePrinter.PutSpan("spanMS01", "02GTTT2");
            _invoicePrinter.PutSpan("spanMS02", regID.ToString());
            _invoicePrinter.PutSpan("spanKH01", spanKH01);
            _invoicePrinter.PutSpan("spanKH02", Convert.ToInt16(DateTime.Now.Year)-2000 + "T");
            _invoicePrinter.PutSpan("spanNumber", (maxNumberOfUse-remainUse+1).ToString().PadLeft(7,'0'));
            _invoicePrinter.PutSpan("spanDay", DateTime.Now.Day.ToString().PadLeft(2, '0'));
            _invoicePrinter.PutSpan("spanMonth", DateTime.Now.Month.ToString());
            _invoicePrinter.PutSpan("spanYear", DateTime.Now.Year.ToString());
            _invoicePrinter.PutSpan("spanCompanyName", _companyInfo.Name);
            _invoicePrinter.PutSpan("spanTaxCode", _companyInfo.Taxcode);
            _invoicePrinter.PutSpan("spanAddress", _companyInfo.Address);
            _invoicePrinter.PutSpan("spanPhone", _companyInfo.Phone);
            _invoicePrinter.PutSpan("spanCustomerName", _currentCustomer.FirstName + " " + _currentCustomer.LastName);
            _invoicePrinter.PutSpan("spanCustomerCompany", _currentCustomer.Company);            
            _invoicePrinter.PutSpan("spanCustomerAddress", _currentCustomer.Address);
            _invoicePrinter.PutSpan("spanPaymentType", this.PaymentType.Equals(PaymentTypes.Cash) ? "Tiền mặt" : "Chuyển khoản");
            _invoicePrinter.PutSpan("spanTotal", ((long)Math.Round(this.totalIncTax)).ToString());
            _invoicePrinter.PutSpan("spanTotalText", utilities.Utilities.ReadVND((long)Math.Round(this.totalIncTax)));
            return string.Empty;
        }

        private bool CanSale { get { return (this.totalExTax > 0) ? true : false; } set { } }
        private bool CanRemove { get { return (this.SelectedPackage != null) ? true : false; } set { } }
        private bool CanAddToPackageCollection { get { return (this._currentPackage == null || string.IsNullOrEmpty(this._currentPackage.ProductUNK)) ? false : true; } set { } }
        private bool CanAddNewProduct
        {
            get
            {
                if (string.IsNullOrEmpty(this.CustomerName))
                {
                    return false;
                }
                if (this._pacs.Count>0 && string.IsNullOrEmpty(this._pacs[this._pacs.Count - 1].PackageUNK))
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
        }

        private double totalExTax = 0;
        private double totalIncTax = 0;

        public void EntityViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            //This will get called when the property of an object inside the collection changes
            totalExTax = 0;
            foreach (Package p in this.PackagesCollection)
            {
                totalExTax += p.PackagePrice;
            }

            OnPropertyChanged("TotalPriceExTax"); 
            OnPropertyChanged("TotalPriceIncTax"); 
        }

        private void AddToPackageCollection()
        {
            for (int i = 0; i < this.PackagesCollection.Count; i++)
            {
                Package p = this.PackagesCollection[i];
                if (!string.IsNullOrEmpty(p.ProductUNK) && p.ProductUNK.Equals(this._currentPackage.ProductUNK))
                {
                    MessageBox.Show(Resources.Product_Existing, Resources.App_Title, MessageBoxButton.OK, MessageBoxImage.Information);
                    this.SelectedPackage = p;
                    OnPropertyChanged("SelectedPackage");
                    return;
                }
            }

            int temp = GetRowIndexByItem(this.SelectedPackage);
            this.PackagesCollection[temp] = this._currentPackage;
            this.PackagesCollection[temp].PropertyChanged += EntityViewModelPropertyChanged;
            this.SelectedPackage = this.PackagesCollection[temp];
            OnPropertyChanged("SelectedPackage");
            OnPropertyChanged("PackagesCollection");
            OnPropertyChanged("TotalPriceExTax");
        }

        private void ChangeSaleType()
        {
            if (this.IsWholesale)
            {
                foreach (Package p in this._pacs)
                {
                    p.UnitPrice = p.SaveWholesale;
                }
            }
            else
            {
                foreach (Package p in this._pacs)
                {
                    p.UnitPrice = p.SaveRetail;
                }
            }

            ObservableCollection<Package> tmpOb = new ObservableCollection<Package>();
            foreach (Package p in this._pacs)
            {
                tmpOb.Add(p);
            }

            this._pacs = tmpOb;
            OnPropertyChanged("PackagesCollection");
            OnPropertyChanged("TotalPriceExTax");
        }

        private void RemoveProduct()
        {
            this.SelectedPackage.PropertyChanged -= EntityViewModelPropertyChanged;
            this.PackagesCollection.Remove(this.SelectedPackage);
            this.SelectedPackage = null;
            OnPropertyChanged("SelectedPackage");
            OnPropertyChanged("PackagesCollection");
            OnPropertyChanged("TotalPriceExTax");
        }

        views.windows.AllProductsView dlg =  null;
        private void ChooseProduct()
        {
            dlg = new views.windows.AllProductsView();
            dlg.DataContext = this;
            if (dlg.ShowDialog() == true)
            {
                string description = this.Products[this.RowIndex].Description;
                string serialNo = this.Products[this.RowIndex].SerialNo;

                double price = this._isWholesale ? this.Products[this.RowIndex].WholesalePrice : this.Products[this.RowIndex].RetailPrice;
                this._currentPackage = Package.CreateBusinessPackage(serialNo, description, this.Products[this.RowIndex].CategoryName, price, 1, this.Products[this.RowIndex].Name);

                this._currentPackage.PackageUNK = "Pac-" + Guid.NewGuid().ToString();
                this._currentPackage.ProductUNK = this.Products[this.RowIndex].ProductUNK;

                this._currentPackage.SaveRetail = this.Products[this.RowIndex].RetailPrice;
                this._currentPackage.SaveWholesale = this.Products[this.RowIndex].WholesalePrice;
                this._currentPackage.SaveImportPrice = this.Products[this.RowIndex].ImportPrice;

                if (this.CanAddToPackageCollection)
                {
                    this.AddToPackageCollection();
                }
            }
        }

        private void AddProduct()
        {
            this._pacs.Add(Package.CreatePackage());
            this.SelectedPackage = this._pacs[this._pacs.Count - 1];
            OnPropertyChanged("SelectedPackage");
        }

        /// <summary>
        /// Execute search button (on search dialog)
        /// </summary>
        private void SearchProducts()
        {
            this._proRepo.LoadProductsByCategory((this.SelectedCategory != null) ? this.SelectedCategory.CategoryUNK : string.Empty);

            if (string.IsNullOrEmpty(this.SelectedProperty))
            {
                this.Products = this._proRepo.GetProducts((this.SelectedCategory != null) ? this.SelectedCategory.CategoryUNK : string.Empty);
            }
            else
            {
                this.Products = this._proRepo.GetProductsWthSearchCriteria(
                    (this.SelectedCategory != null) ? this.SelectedCategory.CategoryUNK : string.Empty,
                    this.SelectedProperty,
                    this.SearchCriteria);
            }
        }

        /// <summary>
        /// Execute select product function (on search dialog)
        /// </summary>
        private void SelectProduct()
        {
            this.dlg.DialogResult = true;
            this.dlg.Close();
        }

        /// <summary>
        /// Execute close/cancel function (on search dialog)
        /// </summary>
        private void CloseProducts()
        {
            this.dlg.DialogResult = false;
            this.dlg.Close();
        }

        private void ResetWorkSpace()
        {
            this._pacs.Clear();
        }

        private int GetRowIndexByItem(Package package)
        {
            if (package != null && string.IsNullOrEmpty(package.PackageUNK)) return this._pacs.Count - 1;
            for (int i = 0; i < _pacs.Count; i++)
            {
                if (package.PackageUNK.Equals(_pacs[i].PackageUNK) && !string.IsNullOrEmpty(_pacs[i].PackageUNK) && !string.IsNullOrEmpty(package.PackageUNK)) return i;
            }

            return -1;
        }

        #endregion

        #region Display Customers View

        /// <summary>
        /// Represent ItemSource for select property selected in search dialog
        /// </summary>
        public Dictionary<string, string> CustomerFields { get; set; }

        /// <summary>
        /// Represent Property for search selected in search dialog
        /// </summary>
        public string SelectedCustomerProperty { get; set; }

        /// <summary>
        /// Represent Search Criteria typed in search dialog
        /// </summary>
        public string SearchCustomerCriteria { get; set; }

        /// <summary>
        /// Represent Index of row in listview selected in search dialog
        /// </summary>
        public int CustomerRowIndex { get; set; }

        /// <summary>
        /// Represent DataSource of listview for selecting product in search dialog
        /// </summary>
        public List<Customer> Customers
        {
            get { return this._suppliers; }
            set { this._suppliers = value; base.OnPropertyChanged("Customers"); }
        }

        private RelayCommand _displayCustomersCommand;
        private RelayCommand _selectCustomerCommand;
        private RelayCommand _closeCustomersCommand;
        private RelayCommand _searchCustomersCommand;
        views.windows.AllCustomersView supdlg = null;
        private List<Customer> _suppliers;

        public ICommand DisplayCustomerViewCommand
        {
            get
            {
                if (_displayCustomersCommand == null)
                {
                    _displayCustomersCommand = new RelayCommand(
                        (param) => this.DisplayCustomerView()
                        );
                }
                return _displayCustomersCommand;
            }
        }

        public ICommand SelectCustomerCommand
        {
            get
            {
                if (_selectCustomerCommand == null)
                {
                    _selectCustomerCommand = new RelayCommand(
                        (param) => this.SelectCustomer(),(param)=>CanSelectCustomer
                        );
                }
                return _selectCustomerCommand;
            }
        }

        public ICommand CloseCustomersCommand
        {
            get
            {
                if (_closeCustomersCommand == null)
                {
                    _closeCustomersCommand = new RelayCommand(
                        (param) => this.CloseCustomers()
                        );
                }
                return _closeCustomersCommand;
            }
        }

        public ICommand SearchCustomersCommand
        {
            get
            {
                if (_searchCustomersCommand == null)
                {
                    _searchCustomersCommand = new RelayCommand(
                        (param) => this.SearchCustomers()
                        );
                }
                return _searchCustomersCommand;
            }
        }

        /// <summary>
        /// Execute search button (on search dialog)
        /// </summary>
        private void SearchCustomers()
        {
            if (string.IsNullOrEmpty(this.SelectedCustomerProperty))
            {
                this.Customers = this._cusRepo.GetCustomers();
            }
            else
            {
                this.Customers = this._cusRepo.GetProductsWthSearchCriteria(this.SelectedCustomerProperty, this.SearchCustomerCriteria);
            }
        }

        /// <summary>
        /// Execute select product function (on search dialog)
        /// </summary>
        private void SelectCustomer()
        {
            this.supdlg.DialogResult = true;
            this.supdlg.Close();
        }

        /// <summary>
        /// Execute close/cancel function (on search dialog)
        /// </summary>
        private void CloseCustomers()
        {
            this.supdlg.DialogResult = false;
            this.supdlg.Close();
        }

        private void DisplayCustomerView()
        {
            supdlg = new views.windows.AllCustomersView();
            supdlg.DataContext = this;

            if (supdlg.ShowDialog() == true)
            {
                if (this.CustomerRowIndex != -1 && this.Customers !=null && this.Customers[this.CustomerRowIndex] != null)
                {
                    this._currentCustomer = this.Customers[this.CustomerRowIndex].CreateShallowCopy();
                    this.CustomerCode = this.Customers[this.CustomerRowIndex].CustomerCode;
                    this.CustomerName = this.Customers[this.CustomerRowIndex].FirstName;
                }
            }
        }
        #endregion

        public bool CanSelectCustomer { get { return CustomerRowIndex != -1 ? true : false; } }

        public bool CanSelectProduct { get { return RowIndex != -1 ? true : false; } }

        public override string DisplayName
        {
            get
            {
                try
                {
                    return Resources.Title_Sale;
                }
                catch (Exception ex)
                {
                    return string.Empty;
                }
            }

        }
    }
}
